package com.azier.compare;

import com.azier.annotation.CompareField;
import com.azier.util.ClassUtil;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 1 * @Author: luoj
 * 2 * @Date: 2019/8/20 14:26
 * 3 单个实时比较，静态方法
 */
public class Compare {
    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回差异字段或者相同字段
     * @param o1
     * @param o2
     * @param equals
     * @param <T>
     * @return Map<字段,Map<o1 o2，value>> 当equals为true时，内部map只会有一个键值对 <"o",value>
     */
    public static <T> Map<Field, Map<String, Object>> compare(T o1, T o2,Class<T> t,boolean equals) throws IllegalAccessException {
        List<Field> fieldList = ClassUtil.getFieldList(t);
        return compareBase(o1, o2, equals, fieldList);
    }

    public static <T> Map<Field, Map<String, Object>> compareBase(T o1, T o2, boolean equals, List<Field> fieldList) throws IllegalAccessException {
        Map<Field, Map<String, Object>> fieldMap = new HashMap<>();
        //都为null,返回null
        if(o1==null&&o2==null){
            return null;
        }
        if(fieldList!=null&&!fieldList.isEmpty()){
            for (Field field:fieldList){
                Map<String, Object> o1o2Value = new HashMap<>();

                CompareField compareField = field.getAnnotation(CompareField.class);
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                //o1对象值
                Object o1Value = null;
                Object o2Value = null;
                if(o1!=null){
                    o1Value = field.get(o1);
                }
                if(o2!=null){
                    o2Value = field.get(o2);
                }
                if(o1Value==null){
                    if(o2Value==null){
                        //一样
                        if(equals){
                            o1o2Value.put("o",o1Value);
                            fieldMap.put(field,o1o2Value);
                        }
                    }else {
                        if(o2Value.equals(o1Value)){
                            //一样
                            if(equals){
                                o1o2Value.put("o",o1Value);
                                fieldMap.put(field,o1o2Value);
                            }
                        }else {
                            //不一样
                            if(!equals){
                                o1o2Value.put("o1Value",o1Value);
                                o1o2Value.put("o2Value",o2Value);
                                fieldMap.put(field,o1o2Value);
                            }
                        }
                    }
                }else {
                    if(o1Value.equals(o2Value)){
                        //一样
                        if(equals){
                            o1o2Value.put("o",o1Value);
                            fieldMap.put(field,o1o2Value);
                        }
                    }else {
                        //不一样
                        if(!equals){
                            o1o2Value.put("o1Value",o1Value);
                            o1o2Value.put("o2Value",o2Value);
                            fieldMap.put(field,o1o2Value);
                        }
                    }
                }
            }
        }
        return fieldMap;
    }

    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回相同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o，value>>
     */
    public static <T> Map<Field, Map<String, Object>> compareEquals(T o1, T o2,Class<T> t) throws IllegalAccessException {
        return compare(o1,o2,t,true);
    }
    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回不同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o1 o2，value>>
     */
    public static <T> Map<Field, Map<String, Object>> compareNotEquals(T o1, T o2,Class<T> t) throws IllegalAccessException {
        return compare(o1,o2,t,false);
    }

    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回相同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o，value>>
     */
    public static <T> Map<String, Map<String, Object>> compareEqualsStringField(T o1, T o2,Class<T> t) throws IllegalAccessException {
        Map<Field, Map<String, Object>> result = compare(o1,o2,t,true);
        return getField2StringMap(result);
    }
    /**
     * 当 o1和o2为同类型的对象，比对两者的差异字段，返回不同字段
     * @param o1
     * @param o2
     * @param <T>
     * @return Map<字段,Map<o1 o2，value>>
     */
    public static <T> Map<String, Map<String, Object>> compareNotEqualsStringField(T o1, T o2,Class<T> t) throws IllegalAccessException {
        Map<Field, Map<String, Object>> result = compare(o1,o2,t,false);;
        return getField2StringMap(result);
    }
    private static Map<String, Map<String, Object>> getField2StringMap(Map<Field, Map<String, Object>> result) {
        Map<String, Map<String, Object>> stringField = new HashMap<>();
        if (result != null && !result.isEmpty()) {
            for (Map.Entry<Field, Map<String, Object>> entry : result.entrySet()) {
                CompareField compareField = entry.getKey().getAnnotation(CompareField.class);
                if (compareField != null) {
                    stringField.put(compareField.name(), entry.getValue());
                } else {
                    stringField.put(entry.getKey().getName(), entry.getValue());
                }
            }
        }
        return stringField;
    }
}
